﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace XNA.Common
{
	/// <summary>
	/// Singleton draw class
	/// </summary>
	public class PaintBrush
	{
		public static readonly PaintBrush Brush = new PaintBrush ();

		#region CONSTRUCTION

		private PaintBrush ()
		{
			
		}

		#endregion

		#region PROPERTIES

		public Matrix ViewMatrix
		{
			get;
			set;
		}

		public Matrix ProjectionMatrix
		{
			get;
			set;
		}

		public Effect Effect
		{
			get;
			set;
		}

		#endregion
		
		#region METHODS (PUBLIC)

		public void Initialize (GraphicsDevice graphics)
		{
			_graphicsDevice = graphics;
			_spriteBatch = new SpriteBatch (graphics);

			SetUpCamera ();
		}

		public void LoadContent (ContentManager content)
		{
			Effect = content.Load<Effect> ("StandardEffects");
		}

		public void Draw (Matrix worldMatrix, Technique technique, Texture2D texture, VertexPositionNormalTexture[] vertices)
		{
			Effect.CurrentTechnique = Effect.Techniques[technique.ToString ()];
			Effect.Parameters["xWorld"].SetValue (worldMatrix);
			Effect.Parameters["xView"].SetValue (ViewMatrix);
			Effect.Parameters["xProjection"].SetValue (ProjectionMatrix);
			Effect.Parameters["xTexture"].SetValue (texture);

			foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
			{
				pass.Apply ();

				_graphicsDevice.DrawUserPrimitives (
					PrimitiveType.TriangleList, 
					vertices.ToArray (), 0, vertices.Count() / 3);
			}
		}

		public void DrawModel (Matrix worldMatrix, Technique technique, ModelData modelData)
		{
			foreach (ModelMesh mesh in modelData.Model.Meshes)
			{
				foreach (Effect effect in mesh.Effects)
				{
					effect.CurrentTechnique = effect.Techniques[technique.ToString ()];
					effect.Parameters["xWorld"].SetValue (modelData.Transforms[mesh.ParentBone.Index] * worldMatrix);
					effect.Parameters["xView"].SetValue (ViewMatrix);
					effect.Parameters["xProjection"].SetValue (ProjectionMatrix);
				}

				mesh.Draw ();
			}
		}

		#endregion

		#region METHODS (PRIVATE)
		
		private void SetUpCamera ()
		{
			ViewMatrix = Matrix.CreateLookAt(
				new Vector3(0, 0, 0),
				new Vector3(32, 0, 0),
				new Vector3(0, 1, 0));

			ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView (
				MathHelper.PiOver4,
				_graphicsDevice.Viewport.AspectRatio,
				0.2f,
				1000);
		}

		#endregion
		
		#region FIELDS

		private SpriteBatch _spriteBatch;
		private GraphicsDevice _graphicsDevice;

		#endregion
	}

	public enum Technique
	{
		Pretransformed,
		Colored,
		ColoredNoShading,
		Textured,
		TexturedNoShading,
		PointSprites
	}
}
